﻿//simple with List
/*using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SmartGenerator
{
    class Generator
    {
        int numberLam;
        int currentNum;
        int maxEnclosure; // должен быть больше 2

        Random rand;

        List <int> Fun;
        List <int> Arg1;
        List <int> Arg2;

        public Generator()
        {
            rand = new Random();
        }

        void LamGenerate(int balanceLam, int enclosure, List<int> permissibleVar)
        {
            int[] FunArg1Arg2 = new int[3];
            int typeExp = rand.Next(2);
            if (typeExp == 0 && (numberLam - currentNum) > balanceLam + 3 && enclosure < maxEnclosure) // generate Lam
            {
                for (int i = 0; i < 3; i++)
                {
                    currentNum++;
                    int currentVarLam = currentNum;

                    permissibleVar.Add(currentVarLam);

                    FunArg1Arg2[i] = 3 * numberLam - currentNum;

                    LamGenerate(balanceLam + 2 - i, enclosure + 1, permissibleVar);

                    permissibleVar.Remove(currentVarLam);
                }
            }
            else
            {
                for (int i = 0; i < 3; i++)
                {
                    if (rand.Next(2) == 0)
                    {
                        FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                    else
                    {
                        FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                }
            }
            Fun.Add(FunArg1Arg2[0]);
            Arg1.Add(FunArg1Arg2[1]);
            Arg2.Add(FunArg1Arg2[2]);
        }

        public void Generate(int maxLam, int enclosure)
        {
            do
            {
                GenerateStaticM(maxLam, enclosure);
            } while (currentNum != maxLam);
        }

        void GenerateStaticM(int maxLam, int enclosure)
        {
            numberLam = maxLam > 3 ? maxLam : 3;

            maxEnclosure = enclosure > 1 ? enclosure : 2;

            currentNum = 0;
            List<int> permissibleVar = new List<int>();
            Fun = new List<int>();
            Arg1 = new List<int>();
            Arg2 = new List<int>();

            while(currentNum < numberLam) {
                int[] FunArg1Arg2 = new int[3];
                for (int i = 2; i >= 0; i--)
                {
                    currentNum++;
                    int currentVarLam = currentNum;
                    permissibleVar.Add(currentNum);

                    FunArg1Arg2[2 - i] = 3 * numberLam - currentNum;

                    LamGenerate(i, 1, permissibleVar);

                    permissibleVar.Remove(currentVarLam);
                }
                Fun.Add(FunArg1Arg2[0]);
                Arg1.Add(FunArg1Arg2[1]);
                Arg2.Add(FunArg1Arg2[2]);
            }

            if (currentNum == maxLam)
            {
                System.Console.WriteLine("Max Lam = " + maxLam + " current number Lam = " + currentNum);
                System.Console.WriteLine("Number Call = " + Fun.Count);

                List<int> scales = new List<int>();
                scales.Add(Fun.Count);
                scales.Add(numberLam);
                scales.Add(numberLam * 2);

                writeFunArg1Arg2("Fun.txt", Fun);
                writeFunArg1Arg2("Arg1.txt", Arg1);
                writeFunArg1Arg2("Arg2.txt", Arg2);
                writeFunArg1Arg2("scales.txt", scales);
            }


     //       System.Console.Read();


        }

        void writeFunArg1Arg2(string funNameFile, List<int> curList)
        {
            FileStream fileStream = new FileStream(funNameFile, FileMode.Create);
            using (StreamWriter sw = new StreamWriter(fileStream))
            {
                fileStream.Seek(0, SeekOrigin.End);
                for (int i = 0; i < curList.Count; i++)
                {
                    if (i == 0)
                    {
                        sw.Write(curList[i]);
                    }
                    else
                    {
                        sw.Write(" " + curList[i]);
                    }
                }
                sw.Close();
            }
        }
    
    }
}*/
//simple

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SmartGenerator
{
    class Generator
    {
        int numberLam;
        int currentNum;
        int maxEnclosure; // должен быть больше 2

        Random rand;

        List<int> Fun;
        List<int> Arg1;
        List<int> Arg2;

        public Generator()
        {
            rand = new Random();
        }

        string getNameFolderTests(int type) {
            switch (type)
            {
                case 0:
                    return "StandartTests";
                case 1:
                    return "SimpleTestsWithNestedVariables";
                case 2:
                    return "SimpleTests";
                default:
                    return "some";
            }
        }

        void LamGenerate(int balanceLam, int enclosure, int permissibleVar)
        {
            int[] FunArg1Arg2 = new int[3];
            int typeExp = rand.Next(2);
            if (typeExp == 0 && (numberLam - currentNum) > balanceLam + 3 && enclosure < maxEnclosure) // generate Lam
            {
                for (int i = 0; i < 3; i++)
                {
                    currentNum++;
                    int currentVarLam = currentNum;

                    //     permissibleVar.Add(currentVarLam);

                    FunArg1Arg2[i] = 3 * numberLam - currentNum;

                    LamGenerate(balanceLam + 2 - i, enclosure + 1, currentVarLam);

                    //                    permissibleVar.Remove(currentVarLam);
                }
            }
            else
            {
                for (int i = 0; i < 3; i++)
                {
                    if (rand.Next(2) == 0)
                    {
                        FunArg1Arg2[i] = 2 * numberLam - permissibleVar;//[rand.Next(permissibleVar.Count)];
                    }
                    else
                    {
                        FunArg1Arg2[i] = numberLam - permissibleVar;//[rand.Next(permissibleVar.Count)];
                    }
                }
            }
            Fun.Add(FunArg1Arg2[0]);
            Arg1.Add(FunArg1Arg2[1]);
            Arg2.Add(FunArg1Arg2[2]);
        }

        public void Generate(string numTest, int maxLam, int enclosure, int typeTest)
        {
            do
            {
                GenerateStaticM( numTest,maxLam, enclosure, typeTest);
            } while (currentNum != maxLam);
        }

        void GenerateStaticM(string numTest, int maxLam, int enclosure, int typeTest)
        {
            numberLam = maxLam > 3 ? maxLam : 3;

            maxEnclosure = enclosure > 1 ? enclosure : 2;

            currentNum = 0;
            //List<int> permissibleVar = new List<int>();
            Fun = new List<int>();
            Arg1 = new List<int>();
            Arg2 = new List<int>();

            while (currentNum < numberLam)
            {
                int[] FunArg1Arg2 = new int[3];
                for (int i = 2; i >= 0; i--)
                {
                    currentNum++;
                    int currentVarLam = currentNum;
                    //permissibleVar.Add(currentNum);

                    FunArg1Arg2[2 - i] = 3 * numberLam - currentNum;

                    LamGenerate(i, 1, currentVarLam);

                    // permissibleVar.Remove(currentVarLam);
                }
                Fun.Add(FunArg1Arg2[0]);
                Arg1.Add(FunArg1Arg2[1]);
                Arg2.Add(FunArg1Arg2[2]);
            }

            if (currentNum == maxLam)
            {
                System.Console.WriteLine("Max Lam = " + maxLam + " current number Lam = " + currentNum);
                System.Console.WriteLine("Number Call = " + Fun.Count);

                List<int> scales = new List<int>();
                scales.Add(Fun.Count);
                scales.Add(numberLam);
                scales.Add(numberLam * 2);

                string pathFolder = createFolderForTests(getNameFolderTests(typeTest), numTest,Fun.Count, maxLam, enclosure);

                writeFunArg1Arg2(pathFolder,"Fun.txt", Fun);
                writeFunArg1Arg2(pathFolder, "Arg1.txt", Arg1);
                writeFunArg1Arg2(pathFolder, "Arg2.txt", Arg2);
                writeFunArg1Arg2(pathFolder, "scales.txt", scales);
            }
        }

        string createFolderForTests(string folderTests, string numTest ,int call, int lam, int enclosure)
        {
            string globalFolderTests = Directory.GetCurrentDirectory();
            globalFolderTests = Path.Combine(globalFolderTests, "Tests");

            if(!Directory.Exists(globalFolderTests)) {
                Directory.CreateDirectory(globalFolderTests);
            }

            string pathString = System.IO.Path.Combine(globalFolderTests, folderTests);

            if (!Directory.Exists(pathString))
            {
                Directory.CreateDirectory(pathString);
            }

            string folderName = ""+numTest;// +"e" + enclosure + "c" + call + "l" + lam;
            pathString = System.IO.Path.Combine(pathString, folderName);

            if (!Directory.Exists(pathString))
            {
                Directory.CreateDirectory(pathString);
            }

            return pathString;
        }

        void writeFunArg1Arg2(string pathFolder ,string nameFile, List<int> curList)
        {
            string pathFile = Path.Combine(pathFolder, nameFile);
            FileStream fileStream = new FileStream(pathFile, FileMode.Create);
            using (StreamWriter sw = new StreamWriter(fileStream))
            {
                fileStream.Seek(0, SeekOrigin.End);
                for (int i = 0; i < curList.Count; i++)
                {
                    if (i == 0)
                    {
                        sw.Write(curList[i]);
                    }
                    else
                    {
                        sw.Write(" " + curList[i]);
                    }
                }
                sw.Close();
            }
        }

    }
}


//standart
/*
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace SmartGenerator
{
    class Generator
    {
        int numberLam;
        int currentNum;
        int maxEnclosure; // должен быть больше 2

        Random rand;

        List<int> Fun;
        List<int> Arg1;
        List<int> Arg2;

        public Generator()
        {
            rand = new Random();
        }

        void LamGenerate(int balanceLam, int enclosure, List<int> permissibleVar)
        {
            int[] FunArg1Arg2 = new int[3];
            for (int i = 0; i < 3; i++)
            {
                if (balanceLam < (numberLam - currentNum) && enclosure < maxEnclosure)
                {
                    int typeExp = rand.Next(2);
                    if (typeExp == 0) // generate Lam
                    {
                        currentNum++;
                        int currentVarLam = currentNum;

                        FunArg1Arg2[i] = 3 * numberLam - currentNum;
                        permissibleVar.Add(currentVarLam);

                        if (numberLam - currentNum > 9)
                        {
                            LamGenerate(balanceLam, enclosure + 1, permissibleVar);
                        }
                        else
                        {
                            MandatoryLamGenerate(balanceLam, enclosure + 1, permissibleVar);
                        }
                        permissibleVar.Remove(currentVarLam);
                    }
                    else //generate Var
                    {
                        //adding v1 or v2
                        if (rand.Next(2) == 0)
                        {
                            FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                        }
                        else
                        {
                            FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                        }
                    }
                }
                else //generate Var
                {
                    //adding v1 or v2
                    if (rand.Next(2) == 0)
                    {
                        FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                    else
                    {
                        FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                }
            }
            Fun.Add(FunArg1Arg2[0]);
            Arg1.Add(FunArg1Arg2[1]);
            Arg2.Add(FunArg1Arg2[2]);
        }

        void MandatoryLamGenerate(int balanceLam, int enclosure, List<int> permissibleVar)
        {
            int[] FunArg1Arg2 = new int[3];
            for (int i = 0; i < 3; i++)
            {
                if (balanceLam < (numberLam - currentNum) && enclosure < maxEnclosure) // generate Lam
                {
                    currentNum++;
                    int currentVarLam = currentNum;
                    permissibleVar.Add(currentVarLam);

                    FunArg1Arg2[i] = 3 * numberLam - currentNum;

                    MandatoryLamGenerate(balanceLam, enclosure + 1, permissibleVar);

                    permissibleVar.Remove(currentVarLam);
                }
                else //generate Var
                {
                    //adding v1 or v2
                    if (rand.Next(2) == 0)
                    {
                        FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                    else
                    {
                        FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                    }
                }
            }
            Fun.Add(FunArg1Arg2[0]);
            Arg1.Add(FunArg1Arg2[1]);
            Arg2.Add(FunArg1Arg2[2]);
        }


        public void Generate(int maxLam, int enclosure)
        {
            do
            {
                GenerateStaticM(maxLam, enclosure);
            } while (currentNum != maxLam);
        }

        public void GenerateStaticM(int maxLam, int enclosure)
        {
            numberLam = maxLam > 3 ? maxLam : 3;

            maxEnclosure = enclosure > 1 ? enclosure : 2;

            currentNum = 0;
            List<int> permissibleVar = new List<int>();
            Fun = new List<int>();
            Arg1 = new List<int>();
            Arg2 = new List<int>();

            while (currentNum < numberLam)
            {
                int[] FunArg1Arg2 = new int[3];
                if (numberLam - currentNum > 6)
                {
                    for (int i = 2; i >= 0; i--)
                    {
                        currentNum++;
                        int currentVarLam = currentNum;
                        permissibleVar.Add(currentVarLam);

                        FunArg1Arg2[2 - i] = 3 * numberLam - currentNum;

                        LamGenerate(i, 1, permissibleVar);

                        permissibleVar.Remove(currentVarLam);
                        //осталось замутить, чтобы в конце были сгенерены все лямбды! при numberLam - 3 < 6
                    }
                }
                else
                {
                    for (int i = 2; i >= 0; i--)
                    {
                        currentNum++;
                        int currentVarLam = currentNum;
                        permissibleVar.Add(currentVarLam);

                        FunArg1Arg2[2 - i] = 3 * numberLam - currentNum;

                        MandatoryLamGenerate(i, 1, permissibleVar);

                        permissibleVar.Remove(currentVarLam);
                        //осталось замутить, чтобы в конце были сгенерены все лямбды! при numberLam - 3 < 6
                    }
                }
                Fun.Add(FunArg1Arg2[0]);
                Arg1.Add(FunArg1Arg2[1]);
                Arg2.Add(FunArg1Arg2[2]);
            }

            if (currentNum == maxLam)
            {
                System.Console.WriteLine("Max Lam = " + maxLam + " current number Lam = " + currentNum);
                System.Console.WriteLine("Number Call = " + Fun.Count);

                List<int> scales = new List<int>();
                scales.Add(Fun.Count);
                scales.Add(numberLam);
                scales.Add(numberLam * 2);

                writeFunArg1Arg2("Fun.txt", Fun);
                writeFunArg1Arg2("Arg1.txt", Arg1);
                writeFunArg1Arg2("Arg2.txt", Arg2);
                writeFunArg1Arg2("scales.txt", scales);
            }


            //       System.Console.Read();


        }

        void writeFunArg1Arg2(string funNameFile, List<int> curList)
        {
            FileStream fileStream = new FileStream(funNameFile, FileMode.Create);
            using (StreamWriter sw = new StreamWriter(fileStream))
            {
                fileStream.Seek(0, SeekOrigin.End);
                for (int i = 0; i < curList.Count; i++)
                {
                    if (i == 0)
                    {
                        sw.Write(curList[i]);
                    }
                    else
                    {
                        sw.Write(" " + curList[i]);
                    }
                }
                sw.Close();
            }
        }

    }
}
*/

//hz
/*
           void LamGenerate(int balanceLam, int enclosure, List<int> permissibleVar)
           {
               int[] FunArg1Arg2 = new int[3];
               for (int i = 0; i < 3; i++)
               {
                   if (balanceLam < (numberLam - currentNum) && enclosure < maxEnclosure)
                   {
                       int typeExp = rand.Next(2);
                       if (typeExp == 0) // generate Lam
                       {
                           currentNum++;
                           int currentVarLam = currentNum;
                           permissibleVar.Add(currentNum);

                           FunArg1Arg2[i] = 3 * numberLam - currentNum;


                           if (numberLam - currentNum > 9)
                           {
                               LamGenerate(balanceLam, enclosure + 1, permissibleVar);
                           }
                           else
                           {
                               MandatoryLamGenerate(balanceLam, enclosure + 1, permissibleVar);
                           }

                           permissibleVar.Remove(currentVarLam);
                       }
                       else //generate Var
                       {
                           //adding v1 or v2
                           if (rand.Next(2) == 0)
                           {
                               FunArg1Arg2[i] = 2*numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                           }
                           else 
                           {
                               FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                           }
                       }
                   }
                   else //generate Var
                   {
                       //adding v1 or v2
                       if (rand.Next(2) == 0)
                       {
                           FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                       }
                       else
                       {
                           FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                       }
                   }
               }
               Fun.Add(FunArg1Arg2[0]);
               Arg1.Add(FunArg1Arg2[1]);
               Arg2.Add(FunArg1Arg2[2]);
           }

           void MandatoryLamGenerate(int balanceLam, int enclosure, List<int> permissibleVar)
           {
               int[] FunArg1Arg2 = new int[3];
               for (int i = 0; i < 3; i++)
               {
                   if (balanceLam < (numberLam - currentNum) && enclosure < maxEnclosure) // generate Lam
                   {
                       currentNum++;
                       int currentVarLam = currentNum;
                       permissibleVar.Add(currentNum);

                       FunArg1Arg2[i] = 3 * numberLam - currentNum;

                       MandatoryLamGenerate(balanceLam, enclosure + 1, permissibleVar);

                       permissibleVar.Remove(currentVarLam);
                   }
                   else //generate Var
                   {
                       //adding v1 or v2
                       if (rand.Next(2) == 0)
                       {
                           FunArg1Arg2[i] = 2 * numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                       }
                       else
                       {
                           FunArg1Arg2[i] = numberLam - permissibleVar[rand.Next(permissibleVar.Count)];
                       }
                   }
               }
               Fun.Add(FunArg1Arg2[0]);
               Arg1.Add(FunArg1Arg2[1]);
               Arg2.Add(FunArg1Arg2[2]);
           }
   */